#pragma once

#include "Header.h"

#include <vector>

#include "Envelope.h"

class EnvelopeManager
{
	std::vector<IEnvelope*> mEnvelopes;

public:
	double CurrentPosition;

	double GetEndPosition()
	{
		double end = 0;
		int size = mEnvelopes.size();
		for (int i = 0; i < size; i++)
		{
			if (mEnvelopes[i]->mX2 > end)
			{
				end = mEnvelopes[i]->mX2;
			}
		}
		return end;
	}

	void Add(IEnvelope* envelope)
	{
		mEnvelopes.push_back(envelope);
	}

	void Remove(IEnvelope* envelope)
	{
		//mEnvelopes.Remove(envelope);
	}

	void ProcessTime(double* input, double* output, int length)
	{
		double endPosition = GetEndPosition();

		// Get total envelope index position.
		int actualEnvelopeI = (int)(fmod(CurrentPosition, endPosition));

		// Get current envelope that contains the index.
		IEnvelope* currentEnvelope = GetEnvelope(actualEnvelopeI);
		double currentEnvelopEnd = currentEnvelope->mX2;

		// Loop samples to process envelope by time.
		for (int i = 0; i < length; i++)
		{
			if (actualEnvelopeI >= currentEnvelopEnd)
			{
				if (actualEnvelopeI >= endPosition)
				{
					actualEnvelopeI = (int)(actualEnvelopeI % (int)endPosition);
					currentEnvelope = GetEnvelope(actualEnvelopeI);
					currentEnvelopEnd = currentEnvelope->mX2;
				}
				else
				{
					// Get new envelope.
					currentEnvelope = GetEnvelope(actualEnvelopeI);
					currentEnvelopEnd = currentEnvelope->mX2;
				}
			}

			currentEnvelope->Process(actualEnvelopeI++, input[i]);
		}
	}

	IEnvelope* GetEnvelope(const double& x)
	{
		int size = mEnvelopes.size();
		for (int i = 0; i < size; i++)
		{
			IEnvelope* envelope = mEnvelopes[i];
			if (x >= envelope->mX1 && x < envelope->mX2)
			{
				return envelope;
			}
		}

		return nullptr;
	}
};